#include <sstream>

#include "actor.h"
#include "control.h"
#include "input.h"
#include "interpolationHelper.h"
#include "renderer.h"
#include "node.h"
#include "action.h"
#include "drawingWidget.h"

Actor::Actor(){


renderer=Renderer::getInstance();
input=Input::getInstance();

location=Vector3f(0,0,0);
rotation=Vector3f(0,0,0);
scale=Vector3f(1,1,1);
orientation=Vector3f(0,0,1);

pivotLocation=Vector3f(0,0,0);

transformMatrix.identity();
originalMatrix.identity();
bUseTransformMatrix=false;

transitionTime=0.5f;

base=NULL;
baseMatrix.identity();
baseNode=NULL;

parent=NULL;
groupID="NULL";

initialLocation=Vector3f(0,0,0);
initialRotation=Vector3f(0,0,0);

color=Vector4f(1,1,1,1);

sceneShaderID="simpleLight";
depthShaderID="depthColor";

soundFileName="NULL";

elapsedTime=0.0;
birth=0.0;

name="Actor";

bPickable=true;
bHidden=false;
bRemoveable=true;
bSelected=false;

drawType=DRAW_TEA;                     //teapot

blendModeOne=GL_SRC_ALPHA;
blendModeTwo=GL_ONE_MINUS_SRC_ALPHA;

mesh="NULL";
vboMeshID="NULL";
textureID="NULL";

controller=NULL;

registerProperties();

//Actor Menu
menuType.push_back("10MoveButton");
menuType.push_back("12RotateButton");

menuProp.push_back("NULL");
menuProp.push_back("NULL");

menuIcon.push_back("icon_move");
menuIcon.push_back("icon_rotate");

menuName.push_back("LOCATION");
menuName.push_back("ROTATION");

//Render properties
bTextured=false;
bShadowTextured=false;
bDepthTextured=false;
bZTest=true;
bUseShader=true;
bFullBright=false;
bDrawOrientation=true;

textTimer=renderer->currentTime;

texScale        = Vector3f(1,1,1);
texRotation     = Vector3f(0,0,0);
texTranslation  = Vector3f(0,0,0);

//for actor loading
actorOffset=0;
nodeOffset=0;

}

Actor::~Actor(){
std::cout << "destroying..." << name << endl;
}

void Actor::registerProperties(){
//register all properties for saving
createMemberID("NAME",&name,this);

createMemberID("LOCATION", &location, this);
createMemberID("ROTATION", &rotation, this);
createMemberID("SCALE", &scale, this);
createMemberID("ORIENTATION", &orientation, this);

createMemberID("TRANSFORMMATRIX",&transformMatrix,this);

createMemberID("BASE",&base,this);
createMemberID("BASEMATRIX",&baseMatrix,this);
createMemberID("PIVOTLOCATION", &pivotLocation, this);
createMemberID("BASENODE",&baseNode, this);

createMemberID("GROUPID",&groupID, this);

createMemberID("COLOR", &color, this);

createMemberID("MESH", &mesh, this);
createMemberID("VBOMESHID", &vboMeshID, this);

createMemberID("TEXTUREID", &textureID, this);
createMemberID("TEXTRANSLATION",&texTranslation,this);
createMemberID("TEXROTATION",&texRotation,this);
createMemberID("TEXSCALE",&texScale,this);

createMemberID("DRAWTYPE",&drawType,this);
createMemberID("BLENDMODEONE",&blendModeOne,this);
createMemberID("BLENDMODETWO",&blendModeTwo,this);

createMemberID("SCENESHADERID",&sceneShaderID,this);
createMemberID("DEPTHSHADERID",&depthShaderID,this);

createMemberID("BHIDDEN",&bHidden,this);
createMemberID("BUSETRANSFORMMATRIX",&bUseTransformMatrix,this);

createMemberID("SOUNDFILENAME",&soundFileName,this);

createMemberID("BSHADOWTEXTURED",&bShadowTextured,this);
createMemberID("BFULLBRIGHT",&bFullBright,this);

createMemberID("BTEXTURED",&bTextured,this);
createMemberID("BDEPTHTEXTURED",&bDepthTextured,this);
createMemberID("BZTEST",&bZTest,this);
createMemberID("BUSESHADER",&bUseShader,this);

createMemberID("TEXTIMER",&textTimer,this);



createMemberID("MENUTYPE", &menuType, this);

}

void Actor::setup(){}

void Actor::trigger(Actor * other){

}

void Actor::setLocation(Vector3f loc){
    if (bUseTransformMatrix)
        transformMatrix.setTranslation(loc);
    else
        location=loc;
}

void Actor::setRotation(Vector3f rot){
    if (bUseTransformMatrix){
        transformMatrix=Matrix4f::createRotationAroundAxis(rot.x*M_PI/180,rot.y*M_PI/180,rot.z*M_PI/180);


        }
    else
        rotation=rot;
}

void Actor::addRotation(Vector3f rot){
    if (bUseTransformMatrix){
        //using OpenGL to generate rotationMatrix
        Matrix4f fullMat;

        glMatrixMode(GL_MODELVIEW);
        glPushMatrix();
        glLoadIdentity();
        glRotatef(rot.y,0,1,0);
        glRotatef(rot.x,1,0,0);
        glRotatef(rot.z,0,0,1);
        glGetFloatv(GL_MODELVIEW_MATRIX,fullMat.data);
        glPopMatrix();
        transformMatrix= transformMatrix * fullMat;
        }
    else
        rotation+=rot;
}


/* update and draw */


void Actor::update(double deltaTime){

elapsedTime+=deltaTime;

    for (int i=0;i<(int)movers.size();i++){
        if (movers[i]!=NULL && !movers[i]->bFinished){  //if we have a mover and it hasn't finished moving yet...
            //update the mover
            movers[i]->interpolate();
            //update our mover buffers
            if (bUseTransformMatrix){
                if (moverMatrices.size()>i) moverMatrices[i]=transformMatrix;
                else moverMatrices.push_back(transformMatrix);
            }else{
                if (moverLocations.size()>i) moverLocations[i]=location;
                else moverLocations.push_back(location);

                if (moverRotations.size()>i) moverRotations[i]=rotation;
                else moverRotations.push_back(rotation);
            }
            //end update mover buffers
        }
    }

    //interpolate the new mover into the old mover
    if (movers.size()>1){

        while(currentTransitions.size()<movers.size()) currentTransitions.push_back(0.0f);

        Vector3f result = moverLocations[0].lerp( currentTransitions[0]/transitionTime , moverLocations[1] );
        if (currentTransitions[0]<transitionTime) currentTransitions[0]=min(transitionTime,currentTransitions[0]+(float)deltaTime* 0.001f);

        for (int i=2;i<(int)movers.size();i++){
            result=result.lerp( currentTransitions[i]/transitionTime , moverLocations[i] );
            if (currentTransitions[i]< transitionTime) currentTransitions[i]=min(transitionTime,currentTransitions[i]+(float)deltaTime* 0.001f);
        }

        setLocation(result);

    }


    //erase movers after finishing transitions
    for (int i=0;i<(int)movers.size();i++){
          //only erase movers if we're finished transitioning!
          if (movers[i]->bFinished && currentTransitions.size()>i && currentTransitions[i]>=transitionTime){
            cout << "deleting mover..." << endl;
            delete(movers[i]);
            movers.erase(movers.begin()+i);
            currentTransitions.erase(currentTransitions.begin()+ i);
            }
    }

    //special case, only one mover ever
    if (movers.size()==1 && movers[0]->bFinished){
            cout << "deleting mover..." << endl;
            delete(movers[0]);
            movers.erase(movers.begin());
            if (currentTransitions.size()>0)
                currentTransitions.erase(currentTransitions.begin());
    }
}

// updates shader uniforms
void Actor::updateShaders(){

     if (!bHidden){
        GLint uniform_location;
        uniform_location = glGetUniformLocationARB(renderer->shaderList[sceneShaderID]->shader, "time");
        glUniform1fARB(uniform_location, renderer->currentTime);
    }
    //OGL_ERROR if depthPass!
    if (bTextured && renderer->bIncludeTextures && !renderer->bDepthPass){
        GLint uniform_location;
        uniform_location = glGetUniformLocationARB(renderer->shaderList[sceneShaderID]->shader, "tex");
        glUniform1iARB(uniform_location, 0);
    }

    if (bShadowTextured && renderer->bIncludeShadows){
        GLint uniform_location;
        uniform_location = glGetUniformLocationARB(renderer->shaderList[sceneShaderID]->shader, "shadowTex");
        glUniform1iARB(uniform_location, 1);
    }


    if (bDepthTextured){
        GLint uniform_location;
        uniform_location = glGetUniformLocationARB(renderer->shaderList[sceneShaderID]->shader, "depthTex");
        glUniform1iARB(uniform_location, 2);
    }

}

//translates, rotates, sets up shaders and textures, then calls a more specifc draw function depending on the drawtype
void Actor::draw(){
}

//simplyfied drawing for picking and maybe collision
void Actor::drawCollision(){

    glPushMatrix();

    glLoadMatrixf(baseMatrix);

    renderer->setupShading("color");

    if (drawType==DRAW_PLANE) renderer->drawPlane(0.0,0.0,scale.x, -scale.y, color );
    else if (drawType==DRAW_PARTICLES) {                        //ATTENTION! Particles are drawn as Cubes!
                                                                //also: ParticleSystem overwrites drawCollision...
        glutSolidCube(1/scale.x);
        }
    else if (drawType==DRAW_VBOMESH){                       //TODO: this will fuck up a lot of things...
        //for sprite based characters, give em a handle to select them with
        if (renderer->vboList[vboMeshID]->vertexInterpretation==GL_POINTS)
            glutSolidCube(1/scale.x);
        else
            drawVBOMesh();
        }

    else if (drawType==DRAW_MESH)       drawMesh();                 //Mesh
    else if (drawType==DRAW_SPRITE)     drawSprite();
    else if (drawType==DRAW_CUBE)       drawCube();                 //Mesh
    else if (drawType==DRAW_TEA)        drawTeapot();
    else if (drawType==DRAW_SKELETAL)   drawSkeletal();

    glPopMatrix();
}


void Actor::drawMesh(){

glScalef(scale.x,scale.y,scale.z);
if (renderer->meshList[mesh])
    DrawOBJ(renderer->meshList[mesh]);
}

void Actor::drawSprite(){

    if (bTextured){
        glEnable(GL_TEXTURE_2D);
        glEnable(GL_POINT_SPRITE_ARB);
        }
    glBegin(GL_POINTS);
        glVertex4f(0,0,0,scale.x*0.1);
    glEnd();
    if (bTextured){
        glDisable(GL_TEXTURE_2D);
        glDisable(GL_POINT_SPRITE_ARB);
        }

}

//Plane is aligned at Top Left corner
void Actor::drawPlane(){
}

void Actor::drawParticles(){}

void Actor::drawTeapot(){

glColor4f(color.r,color.g,color.b,color.a);
glFrontFace(GL_CW);
glutSolidTeapot(scale.x/2);
glFrontFace(GL_CCW);
}

void Actor::drawCube(){

glColor4f(color.r,color.g,color.b,color.a);
glutSolidCube(1/scale.x);
}

void Actor::drawVBOMesh(){

if (renderer->vboList[vboMeshID]){
    renderer->drawColladaMesh(renderer->vboList[vboMeshID]);

    if (renderer->vboList[vboMeshID]->vertexInterpretation==GL_POINTS && !input->controller->bRunning){
        renderer->setupShading("color");
        glutSolidCube(1/scale.x);
        }
    }
}

void Actor::drawSkeletal(){
}

void Actor::drawOrientation(){


    //TODO:add "if selected, draw in color!"

    glColor4f(0,0,0,1);

    glLineWidth(4);

    if (bSelected){
        renderer->setupShading("color");
        glColor4f(1,0,0,1);
        }
    glBegin(GL_LINES);
    glVertex3f(0,0,0);
    glVertex3f(1,0,0);
    glEnd();

    if (bSelected)
        glColor4f(0,1,0,1);
    glBegin(GL_LINES);
    glVertex3f(0,0,0);
    glVertex3f(0,1,0);
    glEnd();

    if (bSelected)
        glColor4f(0,0,1,1);
    glBegin(GL_LINES);
    glVertex3f(0,0,0);
    glVertex3f(0,0,1);
    glEnd();

}

void Actor::reset(){}

/* control start/stop */

void Actor::start(){}
void Actor::stop(){}

/* saving/loading stuff */

//saves all properties as defined in registerProperties
TiXmlElement* Actor::save(TiXmlElement *root){

TiXmlElement * element = new TiXmlElement( "Actor" );
element->SetAttribute("name", name);
TiXmlText * text = new TiXmlText( typeid(*this).name() );
element->LinkEndChild( text );

std::map <std::string, memberID>::iterator it;

for ( it=property.begin() ; it != property.end(); it++ )
  {
  TiXmlElement * property=new TiXmlElement(it->first);
  string value = memberToString(&it->second);
  property->LinkEndChild ( new TiXmlText( value));
  element->LinkEndChild( property );
  }

return element;
}

//loads all properties as defined in registerProperties
void Actor::load(TiXmlElement *myInfo){

    std::map <std::string, memberID>::iterator it;

    for ( it=property.begin() ; it != property.end(); it++ )
      {
      TiXmlElement * property=NULL;                     //always initialise if you want to check against NULL!
      property=myInfo->FirstChildElement(it->first);
      if (property && property->GetText()!=NULL){        //check if the saved file has this element
        memberFromString(&(it->second),property->GetText());
        //cout << "setting member: "<< property->GetText() << endl;
        }
      else
        cout << "unknown property..." << endl;
      }
}

//reads out a property value as a string
string Actor::memberToString(memberID *mID){

    //Vector3f
    if (mID->memberType->name()==typeid(Vector3f).name() )
       return writeVector3f(mID);

    //float
    if (mID->memberType->name()==typeid(float).name())
        return writeFloat(mID);

    //bool
    if (mID->memberType->name()==typeid(bool).name())
       return writeBool(mID);

    //gluint
    if (mID->memberType->name()==typeid(GLuint).name())
        return writeGLuint(mID);

    //Matrix4f
    if (mID->memberType->name()==typeid(Matrix4f).name())
        return writeMatrix4f(mID);

    //Matrix3f
    if (mID->memberType->name()==typeid(Matrix3f).name())
        return writeMatrix3f(mID);

    //Vector4
    if (mID->memberType->name()==typeid(Vector4f).name())
        return writeVector4f(mID);

    //int
    if (mID->memberType->name()==typeid(int).name())
        return writeInt(mID);

    //double
    if (mID->memberType->name()==typeid(double).name())
        return writeDouble(mID);

    //string
    if (mID->memberType->name()==typeid(string).name())
        return writeString(mID);

    //Actor*
    if (mID->memberType->name()==typeid(Actor*).name())
        return writeActor(mID);

    //Node Pointer
    if (mID->memberType->name()==typeid(Node*).name())
        return writeNode(mID);

    ///vectors

    //Vector Actor*
    if (mID->memberType->name()==typeid(vector<Actor*>).name())
        return writeVecActor(mID);

    //Vector Node*
    if (mID->memberType->name()==typeid(vector<Node*>).name())
        return writeVecNode(mID);

    //Vector String*
    if (mID->memberType->name()==typeid(vector<string>).name())
        return writeVecString(mID);

    //Vector Vec3f*
    if (mID->memberType->name()==typeid(vector<Vector3f>).name())
        return writeVecVector3f(mID);

    //Vector Vec4f*
    if (mID->memberType->name()==typeid(vector<Vector4f>).name())
        return writeVecVector4f(mID);


    return "NULL";
}

//sets a property as defined through registerProperties to a value passed in a string
void Actor::memberFromString(memberID *mID,string value){

    char * cValue;
    cValue = new char [value.size()+1];
    strcpy (cValue, value.c_str());



    //give special priority to locations and other vectors!
    if (setPropertyTo (mID, readVector3f(cValue)))
        return;
    if (setPropertyTo (mID, readVector4f(cValue)))
        return;
    if (setPropertyTo (mID, readMatrix4f(cValue)))
        return;
    if (setPropertyTo (mID, readBool(cValue)))
        return;
    if (setPropertyTo (mID, readGLuint(cValue)))
        return;
    if (setPropertyTo (mID, readInt(cValue)))
        return;
    if (setPropertyTo (mID, readFloat(cValue)))
        return;
    if (setPropertyTo (mID, readDouble(cValue)))
        return;
    if (setStringPropertyTo(mID, readString(cValue)))
        return;

    if (setNodePropertyTo(mID, readNode(cValue)))
        return;

    if (setActorPropertyTo(mID, readActor(cValue)))
        return;

    ///vectors


    if (setVecPropertyTo (mID,readVecString(cValue)))
        return;

    //TODO:This will leak a bit of memory!
    cValue = new char [value.size()+1];
    strcpy (cValue, value.c_str());

    if (setVecPropertyTo (mID,readVecActor(cValue)))
        return;

    cValue = new char [value.size()+1];
    strcpy (cValue, value.c_str());

    if (setVecPropertyTo (mID,readVecNode(cValue)))
        return;

    cValue = new char [value.size()+1];
    strcpy (cValue, value.c_str());

    if (setVecPropertyTo (mID,readVecVector3f(cValue)))
        return;

    cValue = new char [value.size()+1];
    strcpy (cValue, value.c_str());

    if (setVecPropertyTo (mID,readVecVector4f(cValue)))
        return;


}

//gets called from memberFromString! Don't use as standalone function!
bool Actor::setStringPropertyTo(memberID * mID,string s){

    if (mID->memberType->name()==typeid(s).name())
      {
      string * theString=(string*)mID->memberReference;
      *theString=s;
      return true;
      }
    return false;
}


//gets called from memberFromString! Don't use as standalone function!
bool Actor::setActorPropertyTo(memberID * mID,Actor* a){


    const std::type_info* mType;
    mType=&(typeid(a));

    if (mID->memberType->name()==mType->name() )
      {
      //double referencing ftw!!
      //get adress of pointer
      Actor** pa= (Actor**)mID->memberReference;
      //switch content of adress of pointer (wow!)
      if (a)
        *pa=a;
      else
        *pa=NULL;
      return true;
      }
    return false;
}

bool Actor::setNodePropertyTo(memberID * mID,Node* n){


    const std::type_info* mType;
    mType=&(typeid(n));

    if (mID->memberType->name()==mType->name() && n )
      {
      cout << "loading a Node* property!" << endl;
      //double referencing ftw!!
      //get adress of pointer
      Node** pa= (Node**)mID->memberReference;
      //switch content of adress of pointer (wow!)
      *pa=n;
      cout << "referenced Node name: " << (*pa)->name << endl;
      return true;
      }
    return false;
}


/* xml parsing */

string Actor::writeVector3f(memberID* mID){
    char value[512];
    Vector3f * p;
    p=(Vector3f*)mID->memberReference;
    sprintf(value,"vec3f %f %f %f",p->x, p->y, p->z);
    return value;
}

string Actor::writeFloat(memberID* mID){
    char value[512];
    float * p;
    p=(float*)mID->memberReference;
    sprintf(value,"float %f",*p);
    return value;
}

string Actor::writeDouble(memberID* mID){
    char value[512];
    double * p;
    p=(double*)mID->memberReference;
    sprintf(value,"double %f",*p);
    return value;
}

string Actor::writeVector4f(memberID* mID){
    char value[512];
    Vector4f * p;
    p=(Vector4f*)mID->memberReference;
    sprintf(value,"vec4f %f %f %f %f",p->r, p->g, p->b, p->a);
    return value;
}

string Actor::writeBool(memberID* mID){
    char value[512];
    bool * p;
    p=(bool*)mID->memberReference;
    sprintf(value,"bool %i",*p);
    return value;
}

string Actor::writeGLuint(memberID* mID){
    char value[512];
    GLuint * p;
    p=(GLuint*)mID->memberReference;
    sprintf(value,"GLuint %i",*p);
    return value;
}

string Actor::writeMatrix4f(memberID* mID){
    char value[512];
    Matrix4f mat4f;
    Matrix4f * p;
    p=(Matrix4f*)mID->memberReference;
    mat4f=*p;
    sprintf(value,"mat4f %f %f %f %f %f %f %f %f %f %f %f %f %f %f %f %f"
                    ,mat4f.data[0], mat4f.data[1], mat4f.data[2], mat4f.data[3],
                     mat4f.data[4], mat4f.data[5], mat4f.data[6], mat4f.data[7],
                     mat4f.data[8], mat4f.data[9], mat4f.data[10],mat4f.data[11],
                     mat4f.data[12],mat4f.data[13],mat4f.data[14],mat4f.data[15]);
    return value;
}

string Actor::writeInt(memberID* mID){
    char value[512];
    int * p;
    p=(int*)mID->memberReference;
    sprintf(value,"int %i",*p);
    return value;
}

string Actor::writeMatrix3f(memberID* mID){
       char value[512];
       Matrix3f * p;
       Matrix3f mat3f;
       p=(Matrix3f*)mID->memberReference;
       mat3f=*p;
       sprintf(value,"mat3f %f %f %f %f %f %f %f %f %f"
                    ,mat3f.data[0], mat3f.data[1], mat3f.data[2],
                     mat3f.data[3], mat3f.data[4], mat3f.data[5],
                     mat3f.data[6], mat3f.data[7], mat3f.data[8]);
       return value;
}

string Actor::writeString(memberID* mID){
    string* me=(string*) mID->memberReference;
    string s="string ";
    s+= (*me);
    return s;
}

string Actor::writeNode(memberID* mID){

    char value[512];
    Node* n;
    Node** p;                           //the ugliness that is **!
    p=(Node**)(mID->memberReference);   //We're actually holding the ADRESS of a NODE* in the memberReference
    n=*p;                                //so we need to dereference twice!

    if (n){                                   //save actor position in actorList!
        for (uint i=0; i<renderer->nodeList.size();i++){
            if (renderer->nodeList[i]==n) sprintf(value,"node* %i",i);
        }
    } else sprintf(value,"node* -1");

    return value;
}

string Actor::writeActor(memberID* mID){

    char value[512];
    Actor* a=NULL;
    Actor** p=NULL;                           //the ugliness that is **!
    p=(Actor**)(mID->memberReference);   //We're actually holding the ADRESS of an ACTOR* in the memberReference
    if (p)
        a=*p;                                //so we need to dereference twice!

    if (a){                                   //save actor position in actorList!
        for (uint i=0; i<renderer->actorList.size();i++){
            if (renderer->actorList[i]==a) sprintf(value,"actor* %i",i);
        }
    } else sprintf(value,"actor* -1");

    return value;
}


string Actor::writeVecActor(memberID* mID){

        string fullString="vector";
        vector<Actor*> * myVec = (vector<Actor*> *)mID->memberReference;


        cout << "size of saveable Vector: "<< myVec->size() << endl;
        for (int i=0; i< (int)myVec->size(); i++){
            //create temporary mID
            createMemberID("temp",&((*myVec)[i]), this);
            //add to our string
            fullString+="|" + writeActor(&property["temp"]);
            property.erase("temp");
            }
        return fullString;
}

string Actor::writeVecNode(memberID* mID){

        string fullString="vector";
        vector<Node*> * myVec = (vector<Node*> *)mID->memberReference;
        for (int i=0; i< (int)myVec->size(); i++){
            //create temporary mID
            createMemberID("temp",&((*myVec)[i]), this);
            //add to our string
            fullString+="|" + writeNode(&property["temp"]);
            property.erase("temp");
            }
        return fullString;
}

string Actor::writeVecString(memberID* mID){
       string fullString="vector";
        vector<string> * myVec = (vector<string> *)mID->memberReference;
        for (int i=0; i< (int)myVec->size(); i++){
            //create temporary mID
            createMemberID("temp",&((*myVec)[i]), this);
            //add to our string
            fullString+="|" + writeString(&property["temp"]);
            property.erase("temp");
            }
        return fullString;
}

string Actor::writeVecVector3f(memberID* mID){
       string fullString="vector";
        vector<Vector3f> * myVec = (vector<Vector3f> *)mID->memberReference;
        for (int i=0; i< (int)myVec->size(); i++){
            //create temporary mID
            createMemberID("temp",&((*myVec)[i]), this);
            //add to our string
            fullString+="|" + writeVector3f(&property["temp"]);
            property.erase("temp");
            }
        return fullString;
}

string Actor::writeVecVector4f(memberID* mID){
       string fullString="vector";
        vector<Vector4f> * myVec = (vector<Vector4f> *)mID->memberReference;
        for (int i=0; i< (int)myVec->size(); i++){
            //create temporary mID
            createMemberID("temp",&((*myVec)[i]), this);
            //add to our string
            fullString+="|" + writeVector4f(&property["temp"]);
            property.erase("temp");
            }
        return fullString;
}



Vector3f Actor::readVector3f(char* cValue){
Vector3f vec3f;
if( strncmp("vec3f ",cValue,6) == 0 )
    sscanf((cValue+6),"%f%f%f",&vec3f.x,&vec3f.y,&vec3f.z);
return vec3f;
}

Vector4f Actor::readVector4f(char* cValue){
Vector4f vec4f;
if( strncmp("vec4f ",cValue,6) == 0 )
    sscanf((cValue+6),"%f%f%f%f",&vec4f.r,&vec4f.g,&vec4f.b,&vec4f.a);
return vec4f;
}

Matrix4f Actor::readMatrix4f(char* cValue){
Matrix4f mat4f;
if( strncmp("mat4f ",cValue,6) == 0 )
    sscanf((cValue+6),"%f%f%f%f%f%f%f%f%f%f%f%f%f%f%f%f",&mat4f.data[0],&mat4f.data[1],&mat4f.data[2],&mat4f.data[3]
                                                        ,&mat4f.data[4],&mat4f.data[5],&mat4f.data[6],&mat4f.data[7]
                                                        ,&mat4f.data[8],&mat4f.data[9],&mat4f.data[10],&mat4f.data[11]
                                                        ,&mat4f.data[12],&mat4f.data[13],&mat4f.data[14],&mat4f.data[15]);
return mat4f;
}

Matrix3f Actor::readMatrix3f(char* cValue){
Matrix3f mat3f;
if( strncmp("mat3f ",cValue,6) == 0 )
    sscanf((cValue+6),"%f%f%f%f%f%f%f%f%f", &mat3f.data[0],&mat3f.data[1],&mat3f.data[2],
                                            &mat3f.data[3],&mat3f.data[4],&mat3f.data[5],
                                            &mat3f.data[6],&mat3f.data[7],&mat3f.data[8]);
return mat3f;
}

bool Actor::readBool(char* cValue){
bool b=false;
int convBuffer;
if( strncmp("bool ",cValue,5) == 0 )
    sscanf((cValue+5),"%i",&convBuffer);
if (convBuffer>0)
 b=true;
return (bool)b;
}

GLuint Actor::readGLuint(char* cValue){
GLuint glui;
if( strncmp("GLuint ",cValue,7) == 0 )
    sscanf((cValue+7),"%u",&glui);
return glui;
}

int Actor::readInt(char* cValue){
int i;
if( strncmp("int ",cValue,4) == 0 )
    sscanf((cValue+4),"%i",&i);
return i;
}

Actor* Actor::readActor(char* cValue){

    int i=-1;
    if( strncmp("actor* ",cValue,7) == 0 )
        sscanf((cValue+7),"%i",&i);

    if (i >= 0 && i < (int)renderer->actorList.size()){
        return renderer->actorList[i+actorOffset];
        }

    return NULL;
}

Node* Actor::readNode(char* cValue){

    int i=-1;
    if( strncmp("node* ",cValue,6) == 0 )
        sscanf((cValue+6),"%i",&i);

    if (i >= 0 && i < (int)renderer->nodeList.size()){
        cout << "found a node list reference!" << endl;
        return renderer->nodeList[i+nodeOffset];
        }

    return NULL;
}

float Actor::readFloat(char* cValue){
float f;
if( strncmp("float ",cValue,6) == 0 )
    sscanf((cValue+6),"%f",&f);
return f;
}

//sscanf only reads float!
double Actor::readDouble(char* cValue){
double d;
if( strncmp("double ",cValue,7) == 0 )
    sscanf((cValue+7),"%lf",&d);
return d;
}

string Actor::readString(char* cValue){
string s;
if( strncmp("string ",cValue,7) == 0 )
    {
    char * myString = new char[64];
    sscanf((cValue+7),"%s",myString);
    s= myString;
    }
return s;
}


vector<string> Actor::readVecString(char* cValue){

    vector<string> myVec;

    if( strncmp("vector",cValue,6) == 0 ){

        cout << " *************  maybe string Vector!" << endl;
        //split vector part away...
        char* vectorPart = strtok(cValue, "|");

        cout << vectorPart << endl;
        //have to do one more time - first is a blank...
        vectorPart = strtok(NULL, "|"); // Splits spaces between words in st

        cout << vectorPart << endl;
        cout << cValue << endl;

        //push back all
        while(vectorPart!=NULL){
            myVec.push_back(readString(vectorPart));
            vectorPart = strtok(NULL, "|"); // Splits spaces between words in st
        }
    }
    return myVec;
}

vector<Actor*> Actor::readVecActor(char* cValue){

    vector<Actor*> myVec;

    if( strncmp("vector",cValue,6) == 0 ){

        //split vector part away...
        cout << " *************  maybe Actor Vector!" << endl;
        char* vectorPart = strtok(cValue, "|");

        //have to do one more time - first is a blank...
        vectorPart = strtok(NULL, "|"); // Splits spaces between words in st
        //push back all
        while(vectorPart!=NULL){
            myVec.push_back(readActor(vectorPart));
            vectorPart = strtok(NULL, "|"); // Splits spaces between words in st
        }

        for (int i=0;i<(int)myVec.size();i++){
            if (myVec[i])
                cout << myVec[i]->name << endl;
            else
                cout << "no actor found!" << endl;
        }
    }
    return myVec;
}

vector<Node*> Actor::readVecNode(char* cValue){

    vector<Node*> myVec;

    if( strncmp("vector",cValue,6) == 0 ){

        //split vector part away...
        char* vectorPart = strtok(cValue, "|");

        //have to do one more time - first is a blank...
        vectorPart = strtok(NULL, "|"); // Splits spaces between words in st

        //push back all
        while(vectorPart!=NULL){
            myVec.push_back(readNode(vectorPart));
            vectorPart = strtok(NULL, "|"); // Splits spaces between words in st
        }
    }
    return myVec;
}

vector<Vector4f> Actor::readVecVector4f(char* cValue){

    vector<Vector4f> myVec;

    if( strncmp("vector",cValue,6) == 0 ){

        //split vector part away...
        char* vectorPart = strtok(cValue, "|");

        //have to do one more time - first is a blank...
        vectorPart = strtok(NULL, "|"); // Splits spaces between words in st

        //push back all
        while(vectorPart!=NULL){
            myVec.push_back(readVector4f(vectorPart));
            vectorPart = strtok(NULL, "|"); // Splits spaces between words in st
        }
    }
    return myVec;
}

vector<Vector3f> Actor::readVecVector3f(char* cValue){

    vector<Vector3f> myVec;

    if( strncmp("vector",cValue,6) == 0 ){

        //split vector part away...
        char* vectorPart = strtok(cValue, "|");

        //have to do one more time - first is a blank...
        vectorPart = strtok(NULL, "|"); // Splits spaces between words in st

        //push back all
        while(vectorPart!=NULL){
            myVec.push_back(readVector3f(vectorPart));
            vectorPart = strtok(NULL, "|"); // Splits spaces between words in st
        }
    }
    return myVec;
}



/*****************************************
    Life or Death Functions
****************************************/

void Actor::remove(){

    //remove references in other actors
    //go through all actors
    for (unsigned int i=0;i<renderer->actorList.size();i++){
        Actor* myActor=renderer->actorList[i];
        //go through all properties
        std::map <std::string, memberID>::iterator it;
        for ( it=myActor->property.begin() ; it != myActor->property.end(); it++ ){
            //find Actor* properties
            memberID mID=it->second;
            const std::type_info* mType;
            mType=&(typeid(Actor*));
            if (mID.memberType->name()==mType->name()){
                //found an actor property!
                Actor** pa=(Actor**)mID.memberReference;
                //see if it references the Actor we want to delete!
                if (*pa==this){
                    *pa=NULL;   //and set the reference to NULL!
                    }
                }
            }
        }

    //remove references in buttons
    //go through all buttons
    for (unsigned int i=0;i<renderer->buttonList.size();i++){
        Button* myButton=renderer->buttonList[i];
        //go through all properties
        std::map <std::string, memberID>::iterator it;
        for ( it=myButton->property.begin() ; it != myButton->property.end(); it++ ){
            //find Actor* properties
            memberID mID=it->second;
            const std::type_info* mType;
            mType=&(typeid(Actor*));
            if (mID.memberType->name()==mType->name()){
                //found an actor property!
                Actor** pa=(Actor**)mID.memberReference;
                //see if it references the Actor we want to delete!
                if (*pa==this){
                    *pa=NULL;   //and set the reference to NULL!
                    }
                }
            }
        }

    //go through all helpers
    for (unsigned int i=0;i<renderer->helperList.size();i++){
        Actor* myActor=renderer->helperList[i];
        //go through all properties
        std::map <std::string, memberID>::iterator it;
        for ( it=myActor->property.begin() ; it != myActor->property.end(); it++ ){
            //find Actor* properties
            memberID mID=it->second;
            const std::type_info* mType;
            mType=&(typeid(Actor*));
            if (mID.memberType->name()==mType->name()){
                //found an actor property!
                Actor** pa=(Actor**)mID.memberReference;
                //see if it references the Actor we want to delete!
                if (*pa==this){
                    *pa=NULL;   //and set the reference to NULL!
                    }
                }
            }
        }

    //remove references in nodes
    //go through all nodes
    for (unsigned int i=0;i<renderer->nodeList.size();i++){
        Node* myNode=renderer->nodeList[i];
        //go through all properties
        std::map <std::string, memberID>::iterator it;
        for ( it=myNode->property.begin() ; it != myNode->property.end(); it++ ){
            //find Actor* properties
            memberID mID=it->second;
            const std::type_info* mType;
            mType=&(typeid(Actor*));
            if (mID.memberType->name()==mType->name()){
                //found an actor property!
                Actor** pa=(Actor**)mID.memberReference;
                //see if it references the Actor we want to delete!
                if (*pa==this){
                    *pa=NULL;   //and set the reference to NULL!
                    }
                }
            }
        }
    //remove us from selectedActors
    for (int i=0;i<(int)input->selectedActors.size();i++){
        if(input->selectedActors[i]==this){
            input->selectedActors[i]->remove();
            input->selectedActors.erase(input->selectedActors.begin()+i);
            }
    }

    //check if we're the current drawing!
    if (DrawingWidget::brush && DrawingWidget::brush->drawing ==this)
        DrawingWidget::brush->drawing=NULL;

    for (uint i=0;i<renderer->actorList.size();i++){
        if (renderer->actorList[i]==this)
          renderer->actorList.erase(renderer->actorList.begin()+i);
    }

    //also do for helpers...
    for (uint i=0;i<renderer->helperList.size();i++){
        if (renderer->helperList[i]==this)
          renderer->helperList.erase(renderer->helperList.begin()+i);
    }
    delete(this);
    //free(this);
}

//for runtime Actor creation
void Actor::create(){ renderer->addActor(this); }

bool Actor::createNewActor(string actorIDName){

if (renderer->actorInfo[actorIDName].actorReference)
  {
  renderer->actorInfo[actorIDName].actorReference->create();
  return true;
  }
else
  return false;
}

bool Actor::isA(string className){

//create internal class name
int nameCount=className.length();
std::string s;
std::stringstream out;
out << nameCount;
s = out.str();
className=s.append(className);

//transform to upper case
std::transform(className.begin(), className.end(),className.begin(), ::toupper);

std::string myName=typeid(*this).name();

//TODO: isA is compiler specific!
//TODO: isA is not taking into account if we're a child of anything!

//transform to upper case
std::transform(myName.begin(), myName.end(),myName.begin(), ::toupper);

//cout << myName << " vs " << className << endl;
if (myName==className)
  return true;
else
  return false;
}


